package com.jack.jetpackapp.reflection

import org.junit.Test

/**
 * 反射测试
 *
 * @author Jack 2021-06-10 23:33
 */
class ReflectionTest {

    @Test
    fun test() {
        // 1. 通过Class.forname获取
        val clazz1 = Class.forName("com.jack.jetpackapp.reflection.User")
        println(clazz1)
        // 2. 通过对象.getClass获取
        val clazz2 = User().javaClass
        println(clazz2)
        // 3. 直接通过类名.class获取
        val clazz3 = User::class.java
        println(clazz3)
        println("${clazz1==clazz2}；${clazz1==clazz3}；${clazz2==clazz3}")
        // 4. 获取所有属性
        println("所有属性：------")
        val files = clazz1.declaredFields
        files.forEach {
            println(it)
        }
        println("获取指定属性：-----")
        val field = clazz1.getDeclaredField("name")
        println(field)
        // 5. 获取所有方法
        println("获取所有方法：--------")
        val methods = clazz1.declaredMethods
        methods.forEach {
            println(it)
        }
        println("获取指定方法：=====")
        val method = clazz1.getDeclaredMethod("toString")
        println(method)
        // 6. 获取所有构造方法
        println("获取所有构造方法：=======")
        val cons = clazz1.declaredConstructors
        cons.forEach {
            println(it)
        }
        println("获取指定的构造函数")
        val constructor = clazz1.getConstructor(String::class.java, String::class.java, Int::class.java)
        println(constructor)
        // 7. 通过class创建一个实例
        println("通过class创建实例")
        println(clazz1.newInstance())
        println("调用指定构造函数")
        val user = constructor.newInstance("张辰", "女", 25)
        println(user)
        // 8. 通过放射调用普通方法
        println("通过放射调用普通方法")
        val method1 = clazz1.getDeclaredMethod("setName", String::class.java)
        // 第一个参数是对象，第二个是方法的参数
        method1.invoke(user, "李琛")
        println(user)
        val method2 = clazz1.getDeclaredMethod("setAge", Int::class.java)
        method2.invoke(user, 33)
        println(user)
        val field1 = clazz1.getDeclaredField("name")
        // 放开访问权限
        field1.isAccessible = true
        // 第一个参数是对象，第二个是赋的值
        field1.set(user, "张碧晨")
        println(user)
        field1.isAccessible = false
    }
}